﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using RaveEngine.Engine.Query.Translate;
using System.IO;

namespace RaveEngine.Engine.Query
{
    public class TranslateQuery : BaseRaveQuery
    {
        public TranslateQuery() { }

        public TranslateQuery(string sConfig)
        {
            try
            {
                StringReader sr = new StringReader(sConfig);
                XmlSerializer serializer = new XmlSerializer(typeof(raveTranslateConfig));
                config = (raveTranslateConfig)serializer.Deserialize(sr);
            }
            catch (Exception ex)
            {
                throw new Exception("Invalid Rave Configuration", ex);
            }
        }

        public TranslateQuery(Stream sConfigStream)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(raveTranslateConfig));
                config = (raveTranslateConfig)serializer.Deserialize(sConfigStream);
            }
            catch (Exception ex)
            {
                throw new Exception("Invalid Rave Configuration", ex);
            }
        }

        private static object m_lock_response = new object();

        public override object Process()
        {
            BaseScrape responseTemp;
            string sXsltOutput = string.Empty;
            string sException = string.Empty;
            raveTranslateConfig tconfig = config as raveTranslateConfig;
            TranslateResponse tresponse;

            // Check Cache, Triple Lock Check follows
            tresponse = HttpRuntime.Cache[tconfig.key] as TranslateResponse;
            if (tresponse != null)
            {
                return tresponse;
            }

            lock (m_lock_response)
            {
                // Check if previous thread loaded cache since lock
                tresponse = HttpRuntime.Cache[tconfig.key] as TranslateResponse;

                if (tresponse == null)
                {

                    try
                    {
                        // Scrape Url
                        switch (tconfig.urlMimeType)
                        {
                            case "application/xml":
                            case "xml":
                                responseTemp = new XmlScrape(tconfig.url);
                                break;
                            case "application/json":
                            case "json":
                                throw new NotImplementedException("json parsing not implemented");
                            default: // HTML
                                // Parse  
                                responseTemp = new HtmlScrape(tconfig.url);
                                break;
                        }
                    }
                    catch (Exception exParse)
                    {
                        return new TranslateResponse() { response = string.Format("Upstream uri is not available. url = {0}", tconfig.url), exception = exParse.Message, key = tconfig.key };
                    }

                    // Process the xslt translation
                    if (responseTemp != null)
                    {
                        sXsltOutput = responseTemp.ProcessXslt(HttpContext.Current.Server.MapPath(tconfig.xslt.xsltPath));
                    }

                    // Process Regex, Saving errors to the error field in the response.
                    try
                    {
                        sXsltOutput = QueryHelpers.PostProcessRegex(sXsltOutput, tconfig.xslt.postRegex);
                    }
                    catch (Exception ex)
                    {
                        sException = ex.Message;
                    }
                }

                // Cache the result
                tresponse = new TranslateResponse() { response = sXsltOutput, exception = sException, key = tconfig.key };
                if (tconfig.cache > 0)
                {
                    HttpRuntime.Cache.Insert(tconfig.key, tresponse, null, DateTime.Now.AddSeconds(tconfig.cache), System.Web.Caching.Cache.NoSlidingExpiration);
                }
            }
           

            return tresponse;
        }
    }
}